<template>
  <div>
    <div class="components-container">
      <split-pane split="vertical" @resize="resize">
        <template slot="paneL">
          <el-menu
            :default-active="activeLeftTab"
            class="myTab"
            mode="horizontal"
            background-color="#f7f8fa"
            text-color="#848b96"
            active-text-color="#212835">
            <el-menu-item index="description" @click="activeLeftTab = 'description'">
              <span><i class="el-icon-tickets"/>题目描述</span>
            </el-menu-item>
            <el-menu-item index="comment" @click="activeLeftTab = 'comment'">
              <span><i class="el-icon-chat-line-square"/>评论({{ problem.commentCount }})</span>
            </el-menu-item>
            <el-menu-item index="history" @click="handleTabHistory">
              <span><i class="el-icon-time"/>提交记录</span>
            </el-menu-item>
          </el-menu>
          <vue-custom-scrollbar :settings="settings" class="scroll-area">
            <el-tabs v-model="activeLeftTab" type="card">
              <el-tab-pane name="description">
                <span slot="label"><i class="el-icon-tickets"/>题目描述</span>
                <div class="left-container">
                  <div class="p_description">
                    <div class="p_title">
                      <h2>{{ problem.number }}. {{ problem.name }}</h2>
                    </div>
                    <el-divider/>
                    <markdown-viewer v-model="problem.describe"/>
                    <el-divider/>
                    <el-descriptions :column="1" title="限制">
                      <el-descriptions-item label="时间限制">{{ problem.timeLimit }} ms</el-descriptions-item>
                      <el-descriptions-item label="内存限制">{{ problem.memoryLimit }} kB</el-descriptions-item>
                    </el-descriptions>
                    <el-descriptions :colon="false" title="提示">
                      <el-descriptions-item><span v-html="formatWord(problem.hint)"/></el-descriptions-item>
                    </el-descriptions>
                    <p>
                      <span class="p_b">通过次数</span> <span class="p_n">{{ problem.passCount }}</span>
                      <el-divider direction="vertical"/>
                      <span class="p_b">提交次数</span> <span class="p_n">{{ problem.submitCount }}</span>
                    </p>
                  </div>
                </div>
              </el-tab-pane>
              <el-tab-pane name="comment">
                <span slot="label"><i class="el-icon-chat-line-square"/>评论({{ problem.commentCount }})</span>
                <comment :belong-id="problemId"/>
              </el-tab-pane>
              <el-tab-pane name="history">
                <span slot="label"><i class="el-icon-time"/>提交记录</span>
                <div class="left-container">
                  <div class="p_description">
                    <div v-if="judge.submissionId !== ''" class="submissionBox" style="background-color: hsl(0, 0%, 97%);">
                      <div style="padding: 10px">
                        <el-row>
                          <el-col :span="4" class="res_judgeResult">
                            {{ judge.judgeResult }}
                          </el-col>
                          <el-col :span="20" class="res_a">
                            <router-link
                              :to="'/problem/submission/' + judge.submissionId"
                              target="_blank"
                              class="inlineBlock mySubmission">
                              显示详情<i class="el-icon-arrow-right"/>
                            </router-link>
                          </el-col>
                        </el-row>
                        <el-divider class="submissionDivider"/>
                        <div style="font-size: 13px;" v-html="formatWord(judge.runtimeOutput)"/>
                      </div>
                    </div>

                    <el-table
                      :data="submissions"
                      class="submissionBox"
                      stripe
                      style="width: 100%">
                      <el-table-column
                        label="提交结果">
                        <template slot-scope="scope">
                          <router-link
                            :to="'/problem/submission/' + scope.row.id"
                            :style="{color:((scope.row.judgeResult === 'AC' || scope.row.judgeResult === '答案正确')? '#2db55d' : '#ff2d55')}"
                            target="_blank"
                            class="inlineBlock mySubmission">
                            {{ scope.row.judgeResult }}
                          </router-link>
                        </template>
                      </el-table-column>
                      <el-table-column
                        label="执行用时">
                        <template slot-scope="scope">
                          {{ scope.row.usedTime }}ms
                        </template>
                      </el-table-column>
                      <el-table-column
                        :formatter="usedMemoryFormatter"
                        prop="usedMemory"
                        label="内存消耗"/>
                      <el-table-column
                        prop="languageName"
                        label="语言"/>
                      <el-table-column
                        prop="submitTime"
                        label="提交时间"
                        min-width="160px"/>
                    </el-table>
                  </div>
                </div>
              </el-tab-pane>
            </el-tabs>
          </vue-custom-scrollbar>
        </template>
        <template slot="paneR">
          <div class="right-container">
            <div v-if="consoleFlag" class="r_code">
              <split-pane split="horizontal">
                <template slot="paneL">
                  <div class="a_topBar">
                    <el-row>
                      <el-col :span="24">
                        <div style="float: left">
                          <el-select
                            v-model="choiceLan"
                            class="a_topBar_select"
                            placeholder="请选择"
                            size="mini"
                            @change="changeLan">
                            <el-option
                              v-for="lan in lans"
                              :key="lan.value"
                              :label="lan.label"
                              :value="lan"
                            />
                          </el-select>
                        </div>
                        <div style="float: right">
                          <el-tooltip class="item" effect="dark" content="显示全部编辑器快捷键" placement="bottom">
                            <el-button
                              icon="el-icon-notebook-2"
                              class="a_topBar_btn"
                              circle
                              @click="dialogTipVisible = true"/>
                          </el-tooltip>
                          <el-tooltip class="item" effect="dark" content="还原到默认的代码模版" placement="bottom">
                            <el-button
                              icon="el-icon-refresh-left"
                              class="a_topBar_btn"
                              circle
                              style="margin-left: -10px"
                              @click="resetCurrentLan"/>
                          </el-tooltip>
                          <el-tooltip class="item" effect="dark" content="代码编辑器设置" placement="bottom">
                            <el-button
                              icon="el-icon-setting"
                              class="a_topBar_btn"
                              circle
                              style="margin-left: -10px"
                              @click="dialogSettingVisible = true"/>
                          </el-tooltip>
                          <el-tooltip
                            :content="isFullscreen ? '退出全屏' : '打开全屏'"
                            class="item"
                            effect="dark"
                            placement="bottom">
                            <el-button
                              icon="el-icon-full-screen"
                              class="a_topBar_btn"
                              circle
                              style="margin-left: -10px"
                              @click="click"/>
                          </el-tooltip>
                        </div>
                      </el-col>
                    </el-row>
                  </div>
                  <codemirror
                    v-model="choiceLan.code"
                    :options="cmOptions"
                    :style="{fontSize: settingData.codeFontSize}"
                    @ready="onCmReady"
                  />
                </template>
                <template slot="paneR">
                  <el-menu
                    :default-active="activeCodeTab"
                    class="myTab"
                    mode="horizontal"
                    background-color="#f7f8fa"
                    text-color="#848b96"
                    active-text-color="#212835">
                    <el-menu-item index="test" @click="activeCodeTab = 'test'">
                      <span>测试用例</span>
                    </el-menu-item>
                    <el-menu-item index="result" @click="activeCodeTab = 'result'">
                      <span>代码执行结果</span>
                    </el-menu-item>
                  </el-menu>
                  <el-tabs v-model="activeCodeTab" type="card">
                    <el-tab-pane label="测试用例" name="test">
                      <el-input
                        :rows="7"
                        v-model="test.input"
                        type="textarea"/>
                    </el-tab-pane>
                    <el-tab-pane label="代码执行结果" name="result" class="elTabPane_Result">
                      <el-row style="padding-bottom: 10px">
                        <el-col :span="4" class="res_judgeResult">
                          {{ test.judgeResult }}
                        </el-col>
                        <el-col :span="20" class="res_message">
                          {{ test.message }}
                        </el-col>
                      </el-row>
                      <el-tooltip effect="light" content="执行代码的输出结果" placement="bottom">
                        <el-input
                          :rows="5"
                          v-model="test.runtimeOutput"
                          type="textarea"
                          disabled/>
                      </el-tooltip>
                    </el-tab-pane>
                  </el-tabs>
                </template>
              </split-pane>
            </div>
            <div v-else class="r_code">
              <div class="a_topBar">
                <el-row>
                  <el-col :span="24">
                    <div style="float: left">
                      <el-select
                        v-model="choiceLan"
                        class="a_topBar_select"
                        placeholder="请选择"
                        size="mini"
                        @change="changeLan">
                        <el-option
                          v-for="lan in lans"
                          :key="lan.value"
                          :label="lan.label"
                          :value="lan"
                        />
                      </el-select>
                    </div>
                    <div style="float: right">
                      <el-tooltip class="item" effect="dark" content="显示全部编辑器快捷键" placement="bottom">
                        <el-button
                          icon="el-icon-notebook-2"
                          class="a_topBar_btn"
                          circle
                          @click="dialogTipVisible = true"/>
                      </el-tooltip>
                      <el-tooltip class="item" effect="dark" content="还原到默认的代码模版" placement="bottom">
                        <el-button
                          icon="el-icon-refresh-left"
                          class="a_topBar_btn"
                          circle
                          style="margin-left: -10px"
                          @click="resetCurrentLan"/>
                      </el-tooltip>
                      <el-tooltip class="item" effect="dark" content="代码编辑器设置" placement="bottom">
                        <el-button
                          icon="el-icon-setting"
                          class="a_topBar_btn"
                          circle
                          style="margin-left: -10px"
                          @click="dialogSettingVisible = true"/>
                      </el-tooltip>
                      <el-tooltip
                        :content="isFullscreen ? '退出全屏' : '打开全屏'"
                        class="item"
                        effect="dark"
                        placement="bottom">
                        <el-button
                          icon="el-icon-full-screen"
                          class="a_topBar_btn"
                          circle
                          style="margin-left: -10px"
                          @click="click"/>
                      </el-tooltip>
                    </div>
                  </el-col>
                </el-row>
              </div>
              <codemirror
                v-model="choiceLan.code"
                :options="cmOptions"
                :style="{fontSize: settingData.codeFontSize}"
                @ready="onCmReady"
                @blur="setLocalCode"
              />
            </div>
            <div class="c_footer">
              <div style="float: left">
                <el-button class="c_footer_console_btn" type="text" size="medium" @click="consoleFlag = !consoleFlag">
                  控制台 <i :class="consoleIcon"/>
                </el-button>
                <el-popover
                  placement="top"
                  title="自定义测试"
                  width="300"
                  trigger="click">
                  <span>
                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;在控制台的<strong>测试用例</strong>里输入数据作为您程序的输入，然后点击<strong>执行代码</strong>。
                    <br>
                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;系统会编译并运行您的代码，将<strong>测试用例</strong>作为<span
                    class="c_pop">stdin</span>，在运行结果里展示<span
                    class="c_pop">stdout</span>。如果发生错误，还会展示<strong>错误信息</strong>。</span>
                  <el-button slot="reference" class="c_footer_tip_btn" type="text" size="medium">
                    如何使用自定义测试？
                  </el-button>
                </el-popover>
              </div>
              <div style="float: right">
                <el-button type="success" icon="el-icon-video-play" size="medium" plain @click="testCode">执行代码
                </el-button>
                <el-button type="primary" size="medium" @click="judgeCode">提交测评</el-button>
              </div>
            </div>
          </div>
        </template>
      </split-pane>
    </div>

    <el-dialog :visible.sync="dialogTipVisible" title="编辑器快捷键">
      <el-table :data="tipData" :show-header="false">
        <el-table-column property="key"/>
        <el-table-column property="value"/>
      </el-table>
    </el-dialog>

    <el-dialog :visible.sync="dialogSettingVisible" title="代码编辑器设置">
      <el-form :model="settingData" label-width="80px">
        <el-form-item label="字体设置">
          <el-select
            v-model="settingData.codeFontSize"
            class="c_select"
            size="small"
            placeholder="请选择字体大小"
            @change="changeSetting">
            <el-option label="12px" value="12px"/>
            <el-option label="13px" value="13px"/>
            <el-option label="14px" value="14px"/>
            <el-option label="15px" value="15px"/>
            <el-option label="16px" value="16px"/>
            <el-option label="17px" value="17px"/>
            <el-option label="18px" value="18px"/>
          </el-select>
          <span class="c_span">调整适合你的字体大小。</span>
        </el-form-item>
        <el-form-item label="主题设置">
          <el-select
            v-model="settingData.theme"
            class="c_select"
            size="small"
            placeholder="请选择主题"
            @change="changeSetting">
            <el-option-group
              v-for="themes in codeTheme"
              :key="themes.key"
              :label="themes.key">
              <el-option
                v-for="theme in themes.options"
                :key="theme.value"
                :label="theme.key"
                :value="theme.value"/>
            </el-option-group>
          </el-select>
          <span class="c_span">切换不同的代码编辑器主题，选择适合你的语法高亮。</span>
        </el-form-item>
        <el-form-item label="Tab长度">
          <el-select
            v-model="settingData.tabSize"
            class="c_select"
            size="small"
            placeholder="请选择Tab长度"
            @change="changeSetting">
            <el-option :value="2" label="2个空格"/>
            <el-option :value="4" label="4个空格"/>
            <el-option :value="8" label="8个空格"/>
          </el-select>
          <span class="c_span">选择你想要的 Tab 长度，默认设置为4个空格。</span>
        </el-form-item>
      </el-form>
    </el-dialog>

  </div>
</template>

<script>
import splitPane from 'vue-splitpane'

import vueCustomScrollbar from 'vue-custom-scrollbar'
import 'vue-custom-scrollbar/dist/vueScrollbar.css'

import MarkdownViewer from '@/components/MarkdownViewer'

import { codemirror } from 'vue-codemirror'

import screenfull from 'screenfull'

import Comment from '@/components/Comment'

import Cookies from 'js-cookie'

// import base style
import 'codemirror/lib/codemirror.css'
// 浅色主题
import 'codemirror/theme/3024-day.css'
import 'codemirror/theme/base16-light.css'
import 'codemirror/theme/duotone-light.css'
import 'codemirror/theme/eclipse.css'
import 'codemirror/theme/idea.css'
import 'codemirror/theme/neat.css'
import 'codemirror/theme/neo.css'
// 深色主题
import 'codemirror/theme/3024-night.css'
import 'codemirror/theme/base16-dark.css'
import 'codemirror/theme/duotone-dark.css'
import 'codemirror/theme/abcdef.css'
import 'codemirror/theme/ambiance.css'
import 'codemirror/theme/darcula.css'
import 'codemirror/theme/dracula.css'
// 语言
import 'codemirror/mode/clike/clike'
import 'codemirror/mode/python/python'
// 滚动条
import 'codemirror/addon/scroll/simplescrollbars.css'
import 'codemirror/addon/scroll/simplescrollbars'
// 代码补全提示
import 'codemirror/addon/hint/anyword-hint'
import 'codemirror/addon/hint/css-hint'
import 'codemirror/addon/hint/html-hint'
import 'codemirror/addon/hint/javascript-hint'
import 'codemirror/addon/hint/show-hint.css'
import 'codemirror/addon/hint/show-hint'
import 'codemirror/addon/hint/sql-hint'
import 'codemirror/addon/hint/xml-hint'
// 代码折叠
import 'codemirror/addon/fold/foldgutter.css'
import 'codemirror/addon/fold/foldcode'
import 'codemirror/addon/fold/foldgutter'
import 'codemirror/addon/fold/brace-fold'
import 'codemirror/addon/fold/comment-fold'
import 'codemirror/addon/fold/markdown-fold'
import 'codemirror/addon/fold/xml-fold'
import 'codemirror/addon/fold/indent-fold'
// 选中单词时相同单词也高亮
import 'codemirror/addon/search/match-highlighter'
// 自动补全括号
import 'codemirror/addon/edit/matchbrackets'
import 'codemirror/addon/edit/closebrackets'

import problemApi from '@/api/oj/problem'
import submissionApi from '@/api/oj/submission'

export default {
  name: 'SplitpaneDemo',
  components: {
    splitPane,
    vueCustomScrollbar,
    MarkdownViewer,
    codemirror,
    screenfull,
    Comment
  },
  data() {
    return {
      arrKey: [],
      settings: {
        suppressScrollY: false,
        suppressScrollX: false,
        wheelPropagation: false
      },
      problem: {
        id: '',
        number: 0,
        name: '',
        timeLimit: 0,
        memoryLimit: 0,
        describe: '',
        hint: '',
        categorys: [],
        likeCount: 0,
        collectCount: 0,
        commentCount: 0,
        submitCount: 0,
        passCount: 0
      },
      scrollbarStyle: 'simple',
      cmOptions: {
        theme: 'eclipse',
        mode: 'text/x-java',
        scrollbarStyle: 'simple',
        readOnly: false,
        tabSize: 4, // 制表符
        indentUnit: 4, // 缩进位数
        lineNumbers: true,
        ineWiseCopyCut: true,
        viewportMargin: 1000,
        autofocus: true,
        autocorrect: true,
        spellcheck: true,
        // specialChars: '/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g',
        specialCharPlaceholder: function(ch) {
          const token = document.createElement('span')
          const content = '\u002e'
          token.className = 'cm-invalidchar'
          token.appendChild(document.createTextNode(content))
          token.title = '\\u' + ch.charCodeAt(0).toString(16)
          token.setAttribute('aria-label', token.title)
          return token
        },
        extraKeys: {
          Tab: (cm) => {
            if (cm.somethingSelected()) { // 存在文本选择
              cm.indentSelection('add') // 正向缩进文本
            } else { // 无文本选择
              cm.replaceSelection(Array(cm.getOption('indentUnit') + 1).join(' '), 'end', '+input') // 光标处插入 indentUnit 个空格
            }
          }
        },
        lint: false,
        // 代码折叠
        gutters: [
          'CodeMirror-lint-markers',
          'CodeMirror-linenumbers',
          'CodeMirror-foldgutter'
        ],
        lineWrapping: false,
        foldGutter: true, // 启用行槽中的代码折叠
        autoCloseBrackets: true, // 自动闭合符号
        autoCloseTags: true,
        matchTags: { bothTags: true },
        matchBrackets: true, // 在光标点击紧挨{、]括号左、右侧时，自动突出显示匹配的括号 }、]
        styleSelectedText: true,
        styleActiveLine: true,
        autoRefresh: true,
        highlightSelectionMatches: {
          minChars: 2,
          trim: true,
          style: 'matchhighlight',
          showToken: false
        },
        hintOptions: {
          completeSingle: false
        }
      },
      lans: [{
        value: '1459409143142739969',
        label: 'Java',
        mode: 'text/x-java',
        initCode: `public class Main {
    public static void main(String[] args) {

    }
}`,
        code: `public class Main {
    public static void main(String[] args) {

    }
}`
      }, {
        value: '1459408314524467201',
        label: 'C',
        mode: 'text/x-csrc',
        initCode: `#include <stdio.h>

int main() {
    return 0;
}`,
        code: `#include <stdio.h>

int main() {
    return 0;
}`
      }, {
        value: '1459408932462829570',
        label: 'C++',
        mode: 'text/x-c++src',
        initCode: `#include <iostream>

int main() {
    return 0;
}`,
        code: `#include <iostream>

int main() {
    return 0;
}`
      }, {
        value: '1459409275410182146',
        label: 'Python3',
        mode: 'text/x-python',
        initCode: ``,
        code: ``
      }],
      choiceLan: null,
      localCodeFlag: false,
      notify: null,
      dialogTipVisible: false,
      tipData: [{
        key: '执行代码',
        value: 'CTRL + Q'
      }, {
        key: '行缩进',
        value: 'TAB'
      }, {
        key: '行减少缩进',
        value: 'SHIFT + TAB'
      }, {
        key: '复制',
        value: 'CTRL + C'
      }, {
        key: '剪切',
        value: 'CTRL + X'
      }, {
        key: '撤销',
        value: 'CTRL + Z'
      }, {
        key: '重做',
        value: 'CTRL + SHIFT + Z'
      }],
      dialogSettingVisible: false,
      codeTheme: [{
        key: '浅色主题',
        options: [{
          key: '3024-day',
          value: '3024-day'
        }, {
          key: 'base16-light',
          value: 'base16-light'
        }, {
          key: 'duotone-light',
          value: 'duotone-light'
        }, {
          key: 'eclipse',
          value: 'eclipse'
        }, {
          key: 'idea',
          value: 'idea'
        }, {
          key: 'neat',
          value: 'neat'
        }, {
          key: 'neo',
          value: 'neo'
        }]
      }, {
        key: '深色主题',
        options: [{
          key: '3024-night',
          value: '3024-night'
        }, {
          key: 'base16-dark',
          value: 'base16-dark'
        }, {
          key: 'duotone-dark',
          value: 'duotone-dark'
        }, {
          key: 'abcdef',
          value: 'abcdef'
        }, {
          key: 'ambiance',
          value: 'ambiance'
        }, {
          key: 'darcula',
          value: 'darcula'
        }, {
          key: 'dracula',
          value: 'dracula'
        }]
      }],
      settingData: {
        codeFontSize: '14px',
        theme: 'eclipse',
        tabSize: 4
      },
      consoleFlag: false,
      activeCodeTab: 'test',
      test: {
        input: '',
        judgeResult: '未运行',
        message: '请先运行您的代码',
        runtimeOutput: '请先运行您的代码'
      },
      activeLeftTab: 'description',
      isFullscreen: false,
      websocket: null,
      pageId: '',
      submissions: [],
      judge: {
        submissionId: '',
        judgeResult: '',
        runtimeOutput: ''
      },
      problemId: ''
    }
  },
  computed: {

    consoleIcon() {
      if (this.consoleFlag) {
        return 'el-icon-caret-bottom'
      }
      return 'el-icon-caret-top'
    }

  },
  created() {
    document.addEventListener('keydown', this.handleKeyDown)
    document.addEventListener('keyup', this.handleKeyUp)

    this.initCodeSetting()

    if (this.$route.params && this.$route.params.id) {
      const id = this.$route.params.id
      this.problemId = this.$route.params.id
      this.getProblemInfo(id)
    } else {
      this.$router.push({ path: '/404' })
    }

    this.pageId = new Date().getTime()
  },
  destroyed() {
    document.removeEventListener('keydown', this.handleKeyDown)
    document.removeEventListener('keyup', this.handleKeyUp)

    if (this.websocket !== null) {
      this.websocket.close() // 离开路由之后断开websocket连接
    }
  },
  mounted() {
    this.init()
  },
  beforeDestroy() {
    this.destroy()
  },
  methods: {

    handleKeyDown(e) {
      const that = this
      if (that.arrKey.length > 0) {
        // a-z的按键 长按去重
        if (that.arrKey.indexOf(e.key.toLowerCase()) >= 0) {
          return
        }
      }
      that.arrKey.push(e.key.toLowerCase())
      this.keydown = that.arrKey.join('+')
      // 监听按键捕获
      if (this.keydown === 'control+q') {
        this.keydown = ''
        // 在这里面写你要用快捷键做的事情
        e.preventDefault()// 取消浏览器原有的操作
      }
    },

    handleKeyUp(e) {
      this.arrKey.splice(this.arrKey.indexOf(e.key.toLowerCase()), 1)
      this.keydown = this.arrKey.join('+')
      e.preventDefault()
    },

    getProblemInfo(id) {
      problemApi.getProblemInfo(id).then(res => {
        this.problem = res.result
      }).catch(error => {
        console.log(error)
        this.$router.push({ path: '/404' })
      })
    },

    resize() {
      console.log('resize')
    },

    onCmReady(cm) {
      // 这里的 cm 对象就是 codemirror 对象，等于 this.$refs.myCm.codemirror
      cm.on('inputRead', (cm, obj) => {
        if (obj.text && obj.text.length > 0) {
          const c = obj.text[0].charAt(obj.text[0].length - 1)
          if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
            cm.showHint({ completeSingle: false })
          }
        }
      })
    },

    setLocalCode() {
      const key = this.$route.params.id + '-' + this.choiceLan.label
      if (this.choiceLan.code !== this.choiceLan.initCode) {
        const value = this.choiceLan.code
        localStorage.setItem(key, value)
      } else {
        localStorage.removeItem(key)
      }
    },

    changeLan(lan) {
      this.cmOptions.mode = lan.mode
      this.code = lan.code
      this.getLocalCode()
    },

    getLocalCode() {
      const key = this.$route.params.id + '-' + this.choiceLan.label
      const value = localStorage.getItem(key)
      if (value !== null) {
        this.choiceLan.code = value
        this.localCodeFlag = true
        if (this.notify !== null) {
          this.notify.close()
        }
        const h = this.$createElement
        this.notify = this.$notify({
          dangerouslyUseHTMLString: true,
          position: 'bottom-right',
          offset: 100,
          // message: '您上次编辑到这里，代码已从您浏览器本地的临时存储中恢复了。 <a @click="resetCurrentLan">还原默认代码模版</a>'
          message: h(
            'p', null,
            [
              h('span', null, '您上次编辑到这里，代码已从您浏览器本地的临时存储中恢复了。'),
              h(
                'a',
                {
                  style: 'color: #409EFF;cursor: pointer;',
                  on: {
                    click: this.resetCurrentLan
                  }
                },
                '还原默认代码模版'
              )
            ]
          )
        })
      }
    },

    resetCurrentLan() {
      this.$confirm('您将放弃所有更改并初始化代码！', '确定？', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        const currentLan = this.choiceLan
        currentLan.code = currentLan.initCode
        this.setLocalCode()
      }).catch(() => {
      })
    },

    initCodeSetting() {
      this.choiceLan = this.lans[0]
      this.getLocalCode()

      const settingData = Cookies.get('codeSetting')
      if (settingData !== undefined) {
        this.settingData = JSON.parse((settingData))
        this.cmOptions.theme = this.settingData.theme
        this.cmOptions.tabSize = this.settingData.tabSize
        this.cmOptions.indentUnit = this.settingData.tabSize
      }
    },

    changeSetting() {
      this.cmOptions.theme = this.settingData.theme
      this.cmOptions.tabSize = this.settingData.tabSize
      this.cmOptions.indentUnit = this.settingData.tabSize
      Cookies.set('codeSetting', JSON.stringify(this.settingData))
    },

    click() {
      if (!screenfull.enabled) {
        this.$message({
          message: '你的浏览器不支持全屏',
          type: 'warning'
        })
        return false
      }
      screenfull.toggle()
    },

    change() {
      this.isFullscreen = screenfull.isFullscreen
    },

    init() {
      if (screenfull.enabled) {
        screenfull.on('change', this.change)
      }
    },

    destroy() {
      if (screenfull.enabled) {
        screenfull.off('change', this.change)
      }
    },

    testCode() {
      if (this.$store.state.user.roles && this.$store.state.user.roles.length > 0) {
        if (this.websocket === null) {
          this.initWebSocket()
        }
        const problemJudgeRequest = {
          problemId: this.$route.params.id,
          pageId: this.pageId,
          lanName: this.choiceLan.label,
          code: this.choiceLan.code,
          input: this.test.input
        }
        problemApi.testCode(problemJudgeRequest).then(res => {
          this.$message({
            offset: 50,
            type: 'success',
            message: res.result
          })
        }).catch(error => {
          console.log(error)
        })
      } else {
        if (this.notify !== null) {
          this.notify.close()
        }
        this.$message({
          offset: 50,
          type: 'warning',
          message: '请先登录'
        })
        this.$router.push({ path: '/login?redirect=' + this.$route.path })
      }
    },

    judgeCode() {
      if (this.$store.state.user.roles && this.$store.state.user.roles.length > 0) {
        this.judge.submissionId = ''
        this.judge.judgeResult = ''
        this.judge.runtimeOutput = ''
        if (this.websocket === null) {
          this.initWebSocket()
        }
        const problemJudgeRequest = {
          problemId: this.$route.params.id,
          pageId: this.pageId,
          lanName: this.choiceLan.label,
          code: this.choiceLan.code
        }
        problemApi.judgeCode(problemJudgeRequest).then(res => {
          this.$message({
            offset: 50,
            type: 'success',
            message: res.result
          })
        }).catch(error => {
          console.log(error)
        })
      } else {
        if (this.notify !== null) {
          this.notify.close()
        }
        this.$message({
          offset: 50,
          type: 'warning',
          message: '请先登录'
        })
        this.$router.push({ path: '/login?redirect=' + this.$route.path })
      }
    },

    initWebSocket() { // 初始化websocket
      const wsUri = process.env.BASE_API_WEBSOCKET + '/oj/problem/submission/' + this.$store.getters.id + '/' + this.pageId
      this.websocket = new WebSocket(wsUri)
      this.websocket.onopen = this.websocketOnOpen
      this.websocket.onerror = this.websocketOnError
      this.websocket.onmessage = this.websocketOnMessage
      this.websocket.onclose = this.websocketClose
    },

    websocketOnOpen() { // 连接成功
      console.log('ws连接成功！')
    },

    websocketOnError() { // 连接错误
      console.log('ws错误!')
      this.$message({
        offset: 50,
        message: 'websocket连接失败，请刷新页面重试',
        type: 'error'
      })
    },

    websocketOnMessage(callBack) { // 数据接收
      const jsonData = JSON.parse(callBack.data)
      if (jsonData.type === 0) {
        this.activeCodeTab = 'result'
        this.consoleFlag = true
        this.test.judgeResult = jsonData.judgeResult
        this.test.message = jsonData.message
        this.test.runtimeOutput = jsonData.runtimeOutput
      } else {
        console.log(jsonData)
        this.handleTabHistory()
        this.judge.submissionId = jsonData.submissionId
        this.judge.judgeResult = jsonData.judgeResult
        this.judge.runtimeOutput += jsonData.message
        console.log(this.judge.runtimeOutput)
      }
    },

    websocketClose(e) { // 关闭
      console.log('断开ws连接', e)
    },

    usedMemoryFormatter(row, column) {
      return (row.usedMemory / 1024).toFixed(2) + 'MB'
    },

    handleTabHistory() {
      if (this.$store.state.user.roles && this.$store.state.user.roles.length > 0) {
        this.activeLeftTab = 'history'
        submissionApi.getSubmissionList(this.$route.params.id).then(res => {
          this.submissions = res.result
        }).catch(error => {
          console.log(error)
        })
      } else {
        if (this.notify !== null) {
          this.notify.close()
        }
        this.$message({
          offset: 50,
          type: 'warning',
          message: '请先登录'
        })
        this.$router.push({ path: '/login?redirect=' + this.$route.path })
      }
    },

    formatWord(word) {
      return word.replace(/\n/g, '<br>')
    }

  }
}
</script>

<style>

.scroll-area {
  position: relative;
  margin: auto;
  height: 100%;
}

.components-container {
  position: relative;
  height: calc(100vh - 50px);;
}

.ps-container.scroll-area {
  height: 90%;
}

.left-container {
  height: 100%;
}

.right-container {
  height: 100%;
}

.r_code {
  height: calc(100% - 56px);
}

.p_description {
  padding: 0 20px;
}

.p_title {
  margin: 16px 0px 0px;
}

.p_b {
  color: rgba(132, 139, 150, 1);
  font-size: 12px;
}

.p_n {
  color: rgba(33, 40, 53, 1);
  font-size: 12px;
}

.vue-codemirror {
  height: calc(100% - 40px);
}

.CodeMirror {
  height: 100%;
}

span.cm-matchhighlight {
  background: #D6EAFF !important
}

.a_topBar {
  background: rgb(247, 248, 250, 1);
  height: 40px;
  padding-right: 20px;
}

.a_topBar_select {
  width: 115px;
  border: none;
  border-radius: 3px;
  margin-left: 10px;
  margin-top: 6px;
}

.a_topBar_btn {
  border: 0;
  background: transparent;
}

.a_topBar_btn:hover, .a_topBar_btn:focus {
  background: rgb(247, 248, 250, 1);
  color: rgb(192, 196, 204, 1);
}

.c_select {
  width: 160px;
}

.c_span {
  color: rgb(175, 180, 189, 1);
  margin-left: 10px;
}

.c_footer {
  background: white;
  height: 56px;
  padding: 10px 20px;
  border-top: 1px solid #dddddd;
  position: relative;
}

.c_footer_console_btn, .c_footer_console_btn:hover, .c_footer_console_btn:focus {
  color: rgb(33, 40, 53, 1);
}

.c_footer_tip_btn {
  color: rgb(145, 145, 145, 1);
}

.c_footer_tip_btn:hover, .c_footer_tip_btn:focus {
  color: rgb(172, 172, 172, 1);
}

.c_pop {
  color: #e74c3c;
  background: hsl(0, 0%, 97%);
  border-radius: 3px;
  border: 1px solid hsla(0, 0%, 0%, 0.06);
  padding: 0 3px;
  margin: 0 2px;
  font-size: 12px;
}

.scroll-area .el-tabs__header {
  padding: 0;
  margin: 0;
  border-bottom: none;
}

.scroll-area .el-tabs__nav-scroll {
  height: 0;
}

.right-container .el-tabs__nav-scroll {
  height: 0;
}

.myTab .el-menu-item {
  font-size: 12px;
  height: 40px;
  line-height: 40px;
  border-bottom-color: #ffffff !important;
}

.myTab.el-menu.el-menu--horizontal {
  border-bottom-color: #ffffff !important;
}

.myTab .el-menu-item:hover {
  background-color: #f7f8fa !important;
}

.myTab .el-menu-item.is-active {
  background-color: white !important;
}

.myTab .el-menu-item [class^=el-icon-] {
  margin-right: 2px;
  width: 16px;
  text-align: center;
  font-size: 15px;
}

.myTab .el-menu-item.is-active {
  background-color: white;
}

.screenfull-svg {
  display: inline-block;
  cursor: pointer;
  fill: #5a5e66;;
  width: 20px;
  height: 20px;
  vertical-align: 10px;
}

.elTabPane_Result {
  padding-left: 20px;
  padding-right: 20px;
  padding-bottom: 20px;
}

.res_judgeResult {
  font-size: 16px;
  color: rgba(55.3846, 112.615, 23.3846, 1);
  font-weight: 500;
}

.res_message {
  font-size: 14px;
  font-weight: 500;
  color: rgb(208, 212, 219, 1);
}

.el-textarea.is-disabled .el-textarea__inner {
  cursor: pointer;
}

.mySubmission:hover {
  color: rgb(64, 158, 255);
}

.submissionBox {
  margin-top: 20px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08), 0 1px 2px rgba(0, 0, 0, 0.1);
}

.submissionDivider {
  margin: 10px 0;
}

.res_a {
  color: rgba(132, 139, 150, 1);
  text-decoration: none;
}

.res_a a:hover {
  color: rgba(33, 83, 153, 1);
  text-decoration: none;
}

</style>
